package nayasis.common.message;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Set;
import java.util.StringTokenizer;

import nayasis.common.Const;
import nayasis.common.conf.NConfigulator;
import nayasis.common.log.NLogger;
import nayasis.common.util.FileUtil;
import nayasis.common.util.StringUtil;

/**
 * 코드 기반의 메세지를 관리하는 유틸 클래스
 *
 * @author 기반기술교육팀
 *
 */
public abstract class Message {

    /**
     * 메세지를 관리하는 Pool
     */

    private static HashMap<String, String> messageProperties = new HashMap<String, String>();

    /**
     * 코드값에 해당하는 메세지를 가져온다.
     *
     * <ol>
     *   <li>
     *     <pre>
     * 메세지의 '@' 문자는 치환가능문자로 사용하며,
     * '@' 문자를 그대로 출력하고 싶을 경우 '/@'이라고 적어주어야 한다.
     *
     * 메세지코드 com.0001 이 '@는 사람입니다.' 로 설정되어 있을 경우
     *
     * Message.get( "com.0001", "박태민" ); --> "박태민은 사람입니다."
     * Message.get( "com.0001", "ABC"    ); --> "ABC는 사람입니다."
     *     </pre>
     *   </li>
     *   <li>
     *     <pre>
     * 미정의된 메세지코드를 가져올 경우, 메세지코드가 그대로 출력된다.
     *
     * 만약 merong 이라는 메세지코드가 정의되어 있지 않다면
     *
     * Message.get( "merong" ); --> "merong"
     *     </pre>
     *   </li>
     * </ol>
     *
     *
     * @param code 메세지 코드
     * @param param '@' 문자를 치환할 파라미터
     * @return 코드값에 해당하는 메세지
     */
    public static String get( String code, Object... param ) {
        return StringUtil.format( getMessage(code), param );
    }

    /**
     * Repository에서 코드값에 해당하는 메세지를 가져온다.
     *
     * @param code 메세지 코드
     * @return 코드값에 해당하는 메세지
     */
    private static String getMessage( String code ) {

        String message = messageProperties.get( code );

        return( message == null ) ? code : message;

    }

    /**
     * Message Pool의 내용을 JavaScript로 만든다.
     *
     * @param filePath JavaScript 파일명
     */
    public static void makeJavascriptFile( String filePath ) {

        try {

            FileUtil.makeTextFile( filePath, getJavascriptContents() );

        } catch (IOException e) {
            NLogger.sys.println( e );
        }

    }

    /**
     * 메세지 Pool에 담겨있는 내용을 JavaScript 컨텐츠로 만든다.
     *
     * @return 파일에 기록할 컨텐츠
     */
    private static String getJavascriptContents() {

        StringBuffer contents = new StringBuffer();

        Set<String> keySet = messageProperties.keySet();

        for( String key : keySet ) {

            contents.append( Const.webUi.SCRIPT_MESSAGE_POOL + "[\"" );
            contents.append( key );
            contents.append( "\"]=\"" );
            contents.append( StringUtil.escapeJson(getMessage(key)) );
            contents.append( "\";\r\n" );

        }

        return contents.toString();

    }

    /**
     * 메세지파일(property형식)을 메모리에 적재한다.
     * 
     * <pre>
     * /resource/conf/common.xml 파일의 /common/message/file 에 설정되어 있는 값 
     * </pre>
     */
    public static void loadMessagePool() {
        
        String messageFilePath = NConfigulator.getElementValue( "/common/message/file" );
        
        loadMessagePool( messageFilePath );
        
    }
    
    /**
     * 메세지파일(property형식)을 메모리에 적재한다.
     *
     * @param filePath 메세지파일의 경로 (설정 HOME부터 시작하는)
     */
    public static void loadMessagePool( String filePath ) {

        BufferedReader reader = null;
        String         buffer = null;

        StringTokenizer token = null;

        try {

            reader = new BufferedReader( new FileReader(new File(filePath)) );

            while ( (buffer = reader.readLine()) != null ) {

                token = new StringTokenizer( buffer, "=" );

                String key = getNextToken( token );
                String val = getNextToken( token );

                messageProperties.put( key, val );

            }

        } catch (IOException e) {

            NLogger.err.println( e );

        } finally {
            try {
                reader.close();
            } catch (IOException e) {}

        }

    }
    
    public static void clearMessagePool() {
        messageProperties.clear();
    }

    /**
     * Token에서 값을 가져온다. (만약 가져올 Token이 없다면 null 리턴)
     *
     * @param token 값을 가져올 토큰
     * @return Token에 담긴 값
     */
    private static String getNextToken( StringTokenizer token ) {

        if( token == null ) return "";

        String result = null;

        try {
            result = token.nextToken();

        } catch( Exception e ) {}

        return  ( result == null ) ? "" : result.trim();

    }

}
